<?php
require 'couch/couch.php';
require 'couch/couchClient.php';
require 'couch/couchDocument.php';
require 'couch/couchAdmin.php';
require 'couch/couchReplicator.php';
require "nervetattoo/ElasticSearchClient.php";

class ZendX_Controller_Action extends Zend_Controller_Action
{
	public  function init()
	{
		ini_set('memory_limit','-1');
    	set_time_limit(0);
	}
	public function dispatch($action) {
		// 3. Get all request parameters
		$params = $this->_getAllParams();

		// 4. Get all action method parameters
		$method_params_array = $this->get_action_params($action);

		$data = array(); // It will sent to the action

		foreach($method_params_array as $param) 
		{
			$name = $param->getName();		
//			$paramclass = $param->getClass();
//			if ($paramclass != null) 
//			{
//				$obj = $param->getClass()->newInstance($params);
//				$data[$name] = $obj;
//			}
//			else
			if ($param->isOptional()) 
			{
				$data[$name] = !empty($params[$name]) ? $params[$name] : $param->getDefaultValue();
			}
			elseif (!empty($params[$name]))
			{
				$data[$name] = $params[$name];	
			}
			else 
			{
				throw new Exception('Parameter: '.$name.' Cannot be empty');
			}			
		}

		// 5. Invoke the action and pass the request parameters as actions method parameters, according to their order and names.
		call_user_func_array(array($this, $action), $data);
		
		$this->_helper->notifyPostDispatch();
	}
	
	public function couchClient()
 	{
 		ini_set('memory_limit','-1');
    	set_time_limit(0);
    	$couchConfig = Zend_Controller_Front::getInstance()->getParam('bootstrap')->getOption('couchdb');
    	return new couchClient($couchConfig['dsn'], $couchConfig['dbname'], $couchConfig['options']);
 	}
 	
 	public function esClient($index, $type = "default")
 	{
 		$esconfig = Zend_Controller_Front::getInstance()->getParam('bootstrap')->getOption('ElasticSearch');
 		$transport = new ElasticSearchTransportHTTP($esconfig['host'], $esconfig['port']);
		return new ElasticSearchClient($transport, $index, $type);
 	}

    public function now()
    {
    	return date('Y-m-d H:i:s');
    }
    
    public function getSystemDate()
    {
    	return date('Y-m-d');
    }
	
    public function db($name = null)
    {
       $front = Zend_Controller_Front::getInstance();
	   $bootstrap = $front->getParam('bootstrap');
	   
       if (is_null($name)) {            
		    $resource = $bootstrap->getPluginResource('db');
		    if (!is_null($resource))
		    {
		        return $resource->getDbAdapter();
		    }
		    else 
		    {
		        $resource = $bootstrap->getPluginResource('multidb');
		        return $resource->getDefaultDb();
		    }
        } 
        else {
            $resource = $bootstrap->getPluginResource('multidb');
		    return $resource->getDb($name);
        }               
    } 
   	    
    /**
	*send a query to the $url
	* uses PHP cURL API
	*
	* @param string $method HTTP method to use ('GET','POST','PUT','DELETE','COPY')
	* @param string $url URL to fetch
	* @param array $parameters additionnal parameters to send with the request
	* @param string|array|object $data request body
	* @param string $content_type the content type of the sent data (defaults to application/json)
	*
	* @return string|false server response on success, false on error
	*/
    public function curl_query( $method, $url, $parameters = array() , $data = NULL, $content_type = NULL, array $curlOptions = array())
    {
    	if ( !in_array($method, array('GET','POST','PUT','DELETE','COPY') )    )
			throw new Exception("Bad HTTP method: $method");
		
		if ( is_array($parameters) AND count($parameters) )
			$url = $url.'?'.http_build_query($parameters);

		$http = $this->_curl_buildRequest($method,$url,$data, $content_type);
		
		curl_setopt_array($http,$curlOptions);
		
		curl_setopt($http,CURLOPT_HEADER, true);
		curl_setopt($http,CURLOPT_RETURNTRANSFER, true);
		curl_setopt($http,CURLOPT_FOLLOWLOCATION, true);

		$response = curl_exec($http);
		curl_close($http);

		return $response;
    }
    
	/**
	* build HTTP request to send to the server
	* uses PHP cURL API
	*
	* @param string $method HTTP method to use
	* @param string $url the request URL
	* @param string|object|array $data the request body. If it's an array or an object, $data is json_encode()d
	* @param string $content_type the content type of the sent data (defaults to application/json)
	* @return resource CURL request resource
	*/
	protected function _curl_buildRequest($method,$url,$data,$content_type) {
		$http = curl_init($url);
		$http_headers = array('Accept: application/json,text/html,text/plain,*/*') ;
		if ( is_object($data) OR is_array($data) ) {
			$data = json_encode($data);
		}
		if ( $content_type ) {
			$http_headers[] = 'Content-Type: '.$content_type;
		} else {
			$http_headers[] = 'Content-Type: application/json';
		}
//		if ( $this->sessioncookie ) {
//			$http_headers[] = "Cookie: ".$this->sessioncookie;
//		}
		curl_setopt($http, CURLOPT_CUSTOMREQUEST, $method);

		if ( $method == 'COPY') {
			$http_headers[] = "Destination: $data";
		} elseif ($data) {
			curl_setopt($http, CURLOPT_POSTFIELDS, $data);
		}
		curl_setopt($http, CURLOPT_HTTPHEADER,$http_headers);
		return $http;
	}
    
    protected function writeExcel(PHPExcel $excel, array $datas, $sheetTitle='Worksheet1', $colTitles=array(),  $iSheetIndex=0)
    {
    	$sheet = $excel->createSheet($iSheetIndex);
    	$sheet->setTitle($sheetTitle);
    	
    	$rowIndex = 1;
    	    	
    	foreach ($datas as $row)
    	{
    		//col titles
    		if ($rowIndex == 1) {    			
    			$keys = array_keys($datas[0]);
    			$col = 0;
    			foreach ($keys as $key)
    			{
    				$colTitle = array_key_exists($key, $colTitles) ? $colTitles[$key] : $key;
    				$sheet->getCellByColumnAndRow($col, $rowIndex)->setValue($colTitle);
    				$col++;
    			}  
    			$rowIndex++;  			
    		}
    		
    		$col = 0;   		
    		    		
    		foreach ($row as $k => $value)
    		{    
    			if (! is_array($value)) {
    				$sheet->getCellByColumnAndRow($col, $rowIndex)->setValue($value); 
    			}
    			else {
    				$rowIndex = $this->writeNestedArray($sheet, $col, $rowIndex, $value);
    			}			
    			   			
    			$col++;
    		} 
    		$rowIndex++;   		
    	}
    }
    
    /**
     * 导入excel指定sheet的内容到couchdb(如果是之前导出的excel，指定了_id,_rev则会更新，否则做插入)
     * @param PHPExcel_Worksheet $sheet 
     * @param array $colMapping sheet列与document属性的对应关系, 如array('A'=>'name', 'B'=>'age')     
     * @param int $startRow 从第几行开始导入
     * @param $function 回调函数，http://php.net/manual/en/language.types.callable.php
     */
    public function importExcel2Couchdb(PHPExcel_Worksheet $sheet, array $colMapping, $startRow = 2, $function = null)
    {
    	$hRow = $sheet->getHighestRow(); 
		$hCol = $sheet->getHighestColumn();
		$highestColumnIndex = PHPExcel_Cell::columnIndexFromString($hCol);
		
		$docs = array();
		
		for ($row = $startRow; $row <= $hRow; ++ $row) 
		{
			$doc = array();
			for ($col = 0; $col < $highestColumnIndex; ++ $col) 
			{
				$colname = PHPExcel_Cell::stringFromColumnIndex($col);
				
				if (array_key_exists($colname, $colMapping)) 
				{
					$cell = $sheet->getCellByColumnAndRow($col, $row);
            		$val = $cell->getValue();
            		//$dataType = PHPExcel_Cell_DataType::dataTypeForValue($val);
            		
            		$key = $colMapping[$colname];
            		$doc[$key] = $val;
				}            	
			}
			
			if (!is_null($function)) {
				$doc = call_user_func($function, $doc);
			}
			
			$docs[] = $doc;
		}
				
		return $this->couchClient()->storeDocs($docs);		
    }
    
    private function writeNestedArray($sheet, $col, $row, $data)
    {    	
    	foreach ($data as $v)
    	{
    		if (! is_array($v))
    			$sheet->getCellByColumnAndRow($col, $row++)->setValue($v); 
    	}
    	return $row-1;
    }
    
    protected function exportExcel(PHPExcel $excel, $filename, $writerType='Excel2007', $download=true)
    {
    	if ($download) {
    		header('Pragma:public');
			header('Content-Type:application/x-msexecl;name="PhpexcelController.xlsx"');
			header("Content-Disposition:inline;filename=\"$filename.xlsx\"");
    	}
    	
    	$objWriter = PHPExcel_IOFactory::createWriter($excel, 'Excel2007');
		if ($download) {
			$objWriter->save('php://output');
		}
		else 
		{
			$objWriter->save($filename);
		}    	
    }
    
	private function get_action_params($action) {
		$classRef = new ReflectionObject($this);
		$className = $classRef->getName();
		$funcRef = new ReflectionMethod($className, $action);
		$paramsRef = $funcRef->getParameters();
		return $paramsRef;
	}
	
	public function toDBC($str)
	{      
    	$arr = array('０' => '0', '１' => '1', '２' => '2', '３' => '3', '４' => '4',      
        	'５' => '5', '６' => '6', '７' => '7', '８' => '8', '９' => '9',      
            'Ａ' => 'A', 'Ｂ' => 'B', 'Ｃ' => 'C', 'Ｄ' => 'D', 'Ｅ' => 'E',      
            'Ｆ' => 'F', 'Ｇ' => 'G', 'Ｈ' => 'H', 'Ｉ' => 'I', 'Ｊ' => 'J',      
            'Ｋ' => 'K', 'Ｌ' => 'L', 'Ｍ' => 'M', 'Ｎ' => 'N', 'Ｏ' => 'O',      
            'Ｐ' => 'P', 'Ｑ' => 'Q', 'Ｒ' => 'R', 'Ｓ' => 'S', 'Ｔ' => 'T',      
            'Ｕ' => 'U', 'Ｖ' => 'V', 'Ｗ' => 'W', 'Ｘ' => 'X', 'Ｙ' => 'Y',      
            'Ｚ' => 'Z', 'ａ' => 'a', 'ｂ' => 'b', 'ｃ' => 'c', 'ｄ' => 'd',      
            'ｅ' => 'e', 'ｆ' => 'f', 'ｇ' => 'g', 'ｈ' => 'h', 'ｉ' => 'i',      
            'ｊ' => 'j', 'ｋ' => 'k', 'ｌ' => 'l', 'ｍ' => 'm', 'ｎ' => 'n',      
            'ｏ' => 'o', 'ｐ' => 'p', 'ｑ' => 'q', 'ｒ' => 'r', 'ｓ' => 's',      
            'ｔ' => 't', 'ｕ' => 'u', 'ｖ' => 'v', 'ｗ' => 'w', 'ｘ' => 'x',      
            'ｙ' => 'y', 'ｚ' => 'z',      
            '（' => '(', '）' => ')', '〔' => '[', '〕' => ']', '【' => '[',      
            '】' => ']', '〖' => '[', '〗' => ']', '“' => '[', '”' => ']',      
            '‘' => '[', '’' => ']', '｛' => '{', '｝' => '}', '《' => '<',      
            '》' => '>',      
            '％' => '%', '＋' => '+', '—' => '-', '－' => '-', '～' => '-',      
            '：' => ':', '。' => '.', '、' => ',', '，' => '.', '、' => '.',      
            '；' => ',', '？' => '?', '！' => '!', '…' => '-', '‖' => '|',      
            '”' => '"', '’' => '`', '‘' => '`', '｜' => '|', '〃' => '"',      
            '　' => ' ','＄'=>'$','＠'=>'@','＃'=>'#','＾'=>'^','＆'=>'&','＊'=>'*',   
            '＂'=>'"');   
     
    	return strtr($str, $arr);
	}
}